package com.corner.presenter.imp;

import android.support.annotation.NonNull;

import com.amap.api.location.AMapLocation;
import com.corner.app.App;
import com.corner.model.cornerservice.domain.GeoPoint;
import com.corner.model.cornerservice.domain.Info;
import com.corner.model.cornerservice.domain.Location;
import com.corner.model.cornerservice.domain.User;
import com.corner.model.cornerservice.helper.AttentionHelper;
import com.corner.model.cornerservice.helper.InfoHelper;
import com.corner.model.cornerservice.helper.LocationHelper;
import com.corner.model.cornerservice.helper.SendInfoTask;
import com.corner.presenter.IChannelPresenter;
import com.corner.presenter.base.BasePresenter;
import com.corner.ui.parcel.PoiItem;
import com.corner.ui.view.IChannelView;
import com.corner.utils.CollectionUtil;
import com.corner.utils.DateFormatUtil;
import com.corner.utils.LocationUtil;
import com.corner.utils.NetUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;

/**
 * Created by Administrator on 2015/7/24，22.01.
 * 描述：
 */
public class ChannelPresenter extends BasePresenter<IChannelView> implements IChannelPresenter,Observer {
    public static final int MAX_TIME_SPAN = 20000;
    boolean isLoading;
    private boolean hasMore;
    private Long locationId;
    private List<Info> infos;
    private long lastRefreshTime;
    private List<Info> infosInTask;

    public ChannelPresenter(){
        SendInfoTask.getInstance().addObserver(this);
    }

    @Override
    public void requestInfos(final Long locationId) {
        this.locationId = locationId;
        if (isLoading) {
            return;
        }
        if (!CollectionUtil.isCollectionEmpty(infos)&&!CollectionUtil.isCollectionEmpty(infosInTask)){
            infos.removeAll(infosInTask);
        }
        infosInTask = SendInfoTask.getInstance().getTaskInfosWithLocationId(locationId);
        if (!CollectionUtil.isCollectionEmpty(infosInTask)){
            if (infos==null){
                infos = new ArrayList<>();
            }
            infos.addAll(0, infosInTask);
            view.showRefreshInfos(infos);
            view.showRefreshComplete();
            view.setLoadMoreEnable(hasMore);
            isLoading = false;
        }else {
            if (!isEnableToRefresh()) {
                view.showRefreshComplete();
                return;
            }
            isLoading = true;
            lastRefreshTime = DateFormatUtil.getCurrentTimeInMills();
            InfoHelper.getLocationInfos(locationId, 10, 0).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<List<Info>>() {
                @Override
                public void call(List<Info> infos) {
                    if (view != null) {
                        ChannelPresenter.this.infos = infos;
                        hasMore = infos.size() >= 10;
                        view.showRefreshInfos(infos);
                        view.showRefreshComplete();
                        view.setLoadMoreEnable(hasMore);
                        isLoading = false;
                    }
                }
            }, new Action1<Throwable>() {
                @Override
                public void call(Throwable throwable) {
                    if (view != null)
                        view.showRefreshComplete();
                    isLoading = false;
                }
            });
        }
    }

    /**
     * 是否现在可以刷新
     * @return
     */
    private boolean isEnableToRefresh() {
        return DateFormatUtil.getCurrentTimeInMills() - lastRefreshTime > MAX_TIME_SPAN;
    }

    @Override
    public void loadMoreInfos() {
        if (isLoading || !hasMore) {
            return;
        }
        isLoading = true;
        InfoHelper.getLocationInfos(locationId, 10, infos.size()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<List<Info>>() {
            @Override
            public void call(List<Info> infos) {
                if (view != null) {
                    hasMore = infos.size() >= 10;
                    view.showLoadMoreComplete();
                    view.setLoadMoreEnable(hasMore);
                    infos.addAll(0, ChannelPresenter.this.infos);
                    view.showLoadMoreInfos(infos);
                    ChannelPresenter.this.infos = infos;
                }
                isLoading = false;
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                if (view != null)
                    view.showLoadMoreComplete();
                isLoading = false;
            }
        });
    }


    @Override
    public void requestIsAttention() {
        view.showLoading(true);
        Location location = new Location();
        location.setObjectId(locationId);
        AttentionHelper.getIsAttention(User.getCurrentUser().getObjectId(), location)
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Boolean>() {
            @Override
            public void call(Boolean aBoolean) {
                if (view != null) {
                    view.requestAttentionSucess(aBoolean);
                    view.showLoading(false);
                }
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                if (view != null) {
                    view.showError(throwable.getMessage());
                    view.showLoading(false);
                }
            }
        });
    }

    @Override
    public void cancelAttention() {
        view.showLoading(true);
        Location location = new Location();
        location.setObjectId(locationId);
        AttentionHelper.cancleAttention(User.getCurrentUser().getObjectId(), location)
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Object>() {
            @Override
            public void call(Object object) {
                if (view != null) {
                    view.cancelSucess();
                    view.showLoading(false);
                }
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                if (view != null) {
                    view.showError(throwable.getMessage());
                    view.showLoading(false);
                }
            }
        });
    }

    @Override
    public void attention() {
        view.showLoading(true);
        Location location = new Location();
        location.setObjectId(locationId);
        AttentionHelper.attention(User.getCurrentUser().getObjectId(), location)
                .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Object>() {
            @Override
            public void call(Object object) {
                if (view != null) {
                    view.attentionSucess();
                    view.showLoading(false);
                }
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
                if (view != null) {
                    view.showError(throwable.getMessage());
                    view.showLoading(false);
                }
            }
        });
    }



    @Override
    public void sendInfo(final Info info, boolean isReSend) {
        view.showSending(info, isReSend);
        if (NetUtil.checkNet(App.application)) {
            LocationUtil.getInstance().startLocation();
            LocationUtil.getInstance().getLocation(new LocationUtil.OnLocationGetListener() {
                @Override
                public void onLocationGet(final AMapLocation aMapLocation) {
                    GeoPoint geoPoint = AMapLocation2GeoPoint(aMapLocation);
                    info.setGeoPoint(geoPoint);
                    Location location =  Location.createWithoutData(locationId,Location.class);
                    info.setArea(location);
                    sendInfo(info);
                }
            });
        } else {
            sendInfoError(info);
        }
    }

    @Override
    public void sendInfo(final Info info, final PoiItem item, boolean isReSend) {
        view.showSending(info, isReSend);
        if (NetUtil.checkNet(App.application)) {
            LocationUtil.getInstance().startLocation();
            LocationUtil.getInstance().getLocation(new LocationUtil.OnLocationGetListener() {
                @Override
                public void onLocationGet(AMapLocation aMapLocation) {
                    final GeoPoint geoPoint = AMapLocation2GeoPoint(aMapLocation);
                    info.setGeoPoint(geoPoint);
                    LocationHelper.getLocationByName(item.name, geoPoint).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
                        @Override
                        public void call(Location location) {
                            if (location != null && view != null) {
                                sendInfoWithLocation(location, info);
                            } else {
                                location = getInitLocationWithPoiItem(item);
                                LocationHelper.saveLocation(location).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
                                    @Override
                                    public void call(Location location) {
                                        sendInfoWithLocation(location, info);
                                    }
                                }, new Action1<Throwable>() {
                                    @Override
                                    public void call(Throwable throwable) {
                                        sendInfoError(info);
                                    }
                                });
                            }
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            sendInfoError(info);
                        }
                    });
                }
            });
        } else {
            sendInfoError(info);
        }
    }

    @Override
    public void sendInfo(final Info info, final String locationName, boolean isReSend) {
        view.showSending(info, isReSend);
        if (NetUtil.checkNet(App.application)) {

            LocationUtil.getInstance().startLocation();
            LocationUtil.getInstance().getLocation(new LocationUtil.OnLocationGetListener() {
                @Override
                public void onLocationGet(final AMapLocation aMapLocation) {
                    final GeoPoint infoGeoPoint = AMapLocation2GeoPoint(aMapLocation);
                    info.setGeoPoint(infoGeoPoint);
                    LocationHelper.getLocationByName(locationName, infoGeoPoint).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
                        @Override
                        public void call(Location location) {
                            if (location != null && view != null) {
                                sendInfoWithLocation(location,info);
                            } else {
                                location = getInitLocationWithLocationName(infoGeoPoint, locationName, aMapLocation);
                                LocationHelper.saveLocation(location).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
                                    @Override
                                    public void call(Location location) {
                                        if (view != null && location != null) {
                                            sendInfoWithLocation(location,info);
                                        }
                                    }
                                }, new Action1<Throwable>() {
                                    @Override
                                    public void call(Throwable throwable) {
                                        sendInfoError(info);
                                    }
                                });
                            }
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            sendInfoError(info);
                        }
                    });
                }
            });
        } else {
            sendInfoError(info);
        }
    }

    @NonNull
    private Location getInitLocationWithLocationName(GeoPoint geoPoint, String locationName, AMapLocation aMapLocation) {
        Location location;
        location = new Location();
        location.setGeoPoint(geoPoint);
        location.setLocationName(locationName);
        if (location.getAddress() != null) {
            location.setAddress(aMapLocation.getAddress());
        }
        if (location.getProvince() != null) {
            location.setProvince(aMapLocation.getProvince());
        }
        if (location.getCity() != null) {
            location.setCity(aMapLocation.getCity());
        }
        return location;
    }

    @NonNull
    private Location getInitLocationWithPoiItem(PoiItem item) {
        Location location;
        location = new Location();
        location.setGeoPoint(new GeoPoint(item.latitude, item.longtitude));
        location.setLocationName(item.name);
        location.setAddress(item.address);
        location.setProvince(item.provice);
        location.setCity(item.city);
        return location;
    }

    @NonNull
    private GeoPoint AMapLocation2GeoPoint(AMapLocation aMapLocation) {
        final GeoPoint geoPoint = new GeoPoint();
        geoPoint.setLatitude(aMapLocation.getLatitude());
        geoPoint.setLongtitude(aMapLocation.getLongitude());
        return geoPoint;
    }



    private void sendInfoWithLocation(Location location, Info info) {
        info.setArea(location);
        sendInfo(info);
        view.setLocationId(location.getObjectId());
    }

    /**
     * 消息发送失败
     * @param info
     */
    private void sendInfoError(Info info) {
        if (view != null)
            view.showSendError(info);
    }


    /**
     * 设置区域并发送
     *
     * @param info
     */
    private void sendInfo(final Info info) {
        InfoHelper.sendInfoIntoInfoTask(info).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<Info>() {

            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
                sendInfoError(info);
            }

            @Override
            public void onNext(Info info) {
                if (view != null) {
                    view.sendSucess(info);
                }
            }
        });
    }

    @Override
    public void requestLocationByPoiItem(PoiItem item) {
        GeoPoint geoPoint = new GeoPoint();
        geoPoint.setLatitude(item.latitude);
        geoPoint.setLongtitude(item.longtitude);
        LocationHelper.getLocationByName(item.name, geoPoint).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
            @Override
            public void call(Location location) {
                if (view != null && location != null)
                    view.setLocationId(location.getObjectId());
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
            }
        });
    }

    @Override
    public void requestLocationByName(final String name) {
        LocationUtil.getInstance().startLocation();
        LocationUtil.getInstance().getLocation(new LocationUtil.OnLocationGetListener() {
            @Override
            public void onLocationGet(final AMapLocation aMapLocation) {
                GeoPoint geoPoint = new GeoPoint();
                geoPoint.setLatitude(aMapLocation.getLatitude());
                geoPoint.setLongtitude(aMapLocation.getLongitude());
                LocationHelper.getLocationByName(name, geoPoint).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
                    @Override
                    public void call(Location location) {
                        if (view != null) {
                            view.setLocationName(location.getLocationName());
                            view.setLocationId(location.getObjectId());
                        }
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                    }
                });
            }
        });

    }

    @Override
    public void requestLocationByLocationId(Long locationId) {
        LocationHelper.getLocation(locationId).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Location>() {
            @Override
            public void call(Location location) {
                if (view != null) view.setLocationName(location.getLocationName());
            }
        }, new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {
            }
        });
    }

    @Override
    public void update(Observable observable, Object o) {
        if (locationId!=null)
            requestInfos(locationId);
    }
}
